<?php

class SecurityUser {
    
	// Speichert die Instanz der Klasse
    private static $instance;
    
    //User Information
    private $pkSecurityUser, $fkPrimaryArea, $uname, $email, $realname, $validTo;
	
	private $isGuest;
	
	private $SystemMessages;
	
    //Getters
    public function getPkSecurityUser()    { return $this->pkSecurityUser; }
    public function getEmail()    { return $this->email; }
    public function getRealname() { return $this->realname;}
	public function getUname() {	return $this->uname; }
	public function getValidTo() { return $this->validTo; }
    public function getIsGuest() { return $this->isGuest; }	

    // Ein private Konstruktor; verhindert die direkte Erzeugung des Objektes
    private function __construct() {
    }
	
    public function __destruct() {

    	//Store Messages in Session-Data
    	$_SESSION['SystemMessages'] = $this->SystemMessages;
    	//echo "storing... <pre>"; print_r($this->SystemMessages); echo "</pre>";
    }
    
    public function addSystemMessage($text) {
     	if(!$this->SystemMessages) {
    		$this->SystemMessages = array();
     	}
     	array_push($this->SystemMessages, $text);	
    }
    
    public function getSystemMessages() {
    	
    	$retval = $this->SystemMessages;
    	$this->SystemMessages = null;
    	
    	return $retval;
    }
    
    // Die Singleton Funktion
    /**
     * Enter description here...
     *
     * @return SecurityUser
     */
    public static function getUser() {
    	
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }

    // Halte Benutzer vom Klonen der Instanz ab
    public function __clone() {
    	
        trigger_error('Klonen ist nicht erlaubt.', E_USER_ERROR);
    }
	
    private function loadUserData($data) {
		
    	$cfg = Runtime::getConfiguration();
    	
    	$this->pkSecurityUser = $data['pkSecurityUser'];
   		$this->uname = $data['uname'];
   		$this->email = $data['email'];
   		$this->realname = $data['realname'];
   		$this->validTo = $data['validTo'];
		
   		$this->isGuest = ($this->uname==$cfg["guest_uname"]);
     	
   		$this->SystemMessages = $_SESSION['SystemMessages'];
   		
    }
    
    public static function login($uname, $md5pass, $isSessionLoaded=false) {
    	
    	$cfg = Runtime::getConfiguration();
 	  	$conn = MySQLConnection::getInstance();

 	  	$sql = "SELECT pkSecurityUser, uname, email, realname, validTo 
    			FROM " . $cfg['table_prefix'] . "SecurityUser 
    			WHERE uname='".mysql_escape_string($uname)."' AND pass='".$md5pass."' AND isActive=1 AND (validTo IS NULL OR validTo >= NOW())";
 	  	
    	$data = $conn->quickQuery($sql);
    	
    	if($data['uname'] == $uname && $uname!='') {
    		//Login is OK
    		
    		//Save Session
    		$_SESSION['usr_id'] = $data['pkSecurityUser'];
    		$_SESSION['usr_pass'] = $md5pass;
    		$_SESSION['id'] = session_id();
    		
    		//Save User Information
    		self::$instance->loadUserData($data);
			
    		if(!$isSessionLoaded) {
    			Runtime::logEvent("LoginOk", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
			}
			
    		return true;
    	}
    	else {
			Runtime::logEvent("LoginFailed", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
    		
    		return false;
    	}
    	
    }
    
    public static function loginChallange($uname, $passphrase, $challenge) {
    	
    	if($_SESSION['challenge']!=$challenge && $challenge) {
    		Runtime::logEvent("ChallengeMissmatch", __FILE__, __CLASS__, __FUNCTION__, __LINE__, array("reqChallenge" => $_SESSION['challenge']));
    		return false;
    	}
    	else {
    		
    		//try to load user from DB
	    	$cfg = Runtime::getConfiguration();
	 	  	$conn = MySQLConnection::getInstance();
	
	 	  	$sql = "SELECT pkSecurityUser, uname, pass 
	    			FROM " . $cfg['table_prefix'] . "SecurityUser 
	    			WHERE uname='".mysql_escape_string($uname)."' AND isActive=1 AND (validTo IS NULL OR validTo >= NOW())";
	 	  	
	    	$data = $conn->quickQuery($sql);
    		
	    	//Check Password
	    	if(md5($_SESSION['challenge'] . $data['pass']) == $passphrase) {
	    		return self::login($uname, $data['pass']);
	    	}
	    	else {
	    		//Wrong password in Passphrase
				Runtime::logEvent("ChallengeLoginFailed", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
				return false;	    		
	    	}
    		
    	}
    	
    }
	
    public function loadSession() {
    	
    	$cfg = Runtime::getConfiguration();
    	$conn = MySQLConnection::getInstance();
    	
    	//Try getting Information from DB, based on current $_Session[]
    	$data = null;
    	if(isset($_SESSION['usr_id']) && isset($_SESSION['usr_pass'])) {
	    	$sql = "SELECT uname, pass FROM " .  $cfg['table_prefix'] . "SecurityUser 
	    			WHERE pkSecurityUser='".$_SESSION['usr_id']."' AND pass='".$_SESSION['usr_pass']."' AND isActive=1 AND (validTo IS NULL OR validTo >= NOW())";
	    	
	    	$data = $conn->quickQuery($sql);
    	}
     	
		if($data['uname']!="") {
			//Login with these credentials
			
			return self::login($data['uname'], $data['pass'], true);
		}
		else {
			if(!self::login($cfg['guest_uname'], md5($cfg['guest_pass']), true)) {
			
				//Fatal error, cannot login as guest!$
				Runtime::logEvent("GuestLoginFailed", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
			}
			

			return true;
    	}
    	
    }

    
    public function changePass($newpass) {

    	if($newpass=="") return false;
    	if($this->isGuest) {
			Runtime::logEvent("GuestChangePassFailed", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
			return false;
    	}
    	
    	if($_SESSION['usr_id']!=$this->pkSecurityUser) {
			Runtime::logEvent("ForeignChangePassFailed", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
			return false;
       	}
    	
       	/* Change pass in DB */
       	$md5pass = md5($newpass);
       	
       	$conn = MySQLConnection::getInstance();
       	$cfg = Runtime::getConfiguration();
       	
       	$sql = "UPDATE " .  $cfg['table_prefix'] . "SecurityUser 
    		    SET pass = '$md5pass'
    			WHERE pkSecurityUser='".$_SESSION['usr_id']."'";
	    	
	    if($conn->update($sql)) {
			Runtime::logEvent("ChangePassOK", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
			$_SESSION['usr_pass'] = $md5pass;
			return true;
	    }
	    else {
			Runtime::logEvent("ChangePassFailed", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
			return false;
	    }
       	
       	
    }
    
    public function destroySession() {
		Runtime::logEvent("Logout", __FILE__, __CLASS__, __FUNCTION__, __LINE__);
    	
		//Do not destroy Session, it might be used in an background working thread
		$_SESSION['usr_id'] = null;
		$_SESSION['usr_pass'] = null;
		
		//Destroy all cache entries
		$keys = array_keys($_SESSION);
		foreach ($keys as $key) {
			if(substr($key, 0, 6) == "cache_") {
				$_SESSION[$key] = null;	
			}
		}
		
    }

}

?>